import os,posixpath,urllib

from django.conf                import settings
from django.contrib.auth.models import AnonymousUser
from django.template            import loader
from django.utils               import translation
from sitepal.sitebase.conf      import properties
from sitepal.sitetheme          import CURRENT_THEME_PREFIX

class BaseRenderer(object):
    def __init__(self,theme):
        from sitepal.sitetheme.models import Theme
        assert isinstance(theme,Theme)
        self._theme = theme

    @property
    def theme(self):
        return self._theme

    def contribute_to_theme(self):
        return {
            'common_attributes': self.common_attributes,
            'escape'           : self.escape,
            'safe'             : self.safe,
        }

    def common_attributes(self,attributes):
        output = []
        output.append(self.render_attribute('id',   attributes))
        output.append(self.render_attribute('class',attributes))
        output.append(self.render_attribute('style',attributes))
        output.append(self.render_attribute('title',attributes))
        output.append(self.render_attribute('lang', attributes))
        output.append(self.render_attribute('dir',  attributes))
        return u''.join(output)

    def escape(self,value):
        from django.utils.html import conditional_escape
        
        if value:
            return conditional_escape(value)
        return None

    def safe(self,value):
        from django.utils.safestring import mark_safe

        if value:
            return mark_safe(value)
        return None

    def render_attribute(self,name,value):
        if isinstance(value,dict):
            value = value.get(name)
        if value:
            return u' {0}="{1}"'.format(name,self.escape(value))
        return u''

class ThemeRenderer(BaseRenderer):
    def __init__(self,theme):
        super(ThemeRenderer,self).__init__(theme)
        self._templates = {}

    def contribute_to_theme(self):
        d =  super(ThemeRenderer,self).contribute_to_theme()
        d.update({
            'add_class'                  : self.add_class,
            'format_table_header'        : self.format_table_header,
            'format_table_header_active' : self.format_table_header_active,
            'format_table_header_passive': self.format_table_header_passive,
            'format_table_header_simple' : self.format_table_header_simple,
            'get_user'                   : self.get_user,
            'common_context'             : self.common_context,
            'user_context'               : self.user_context,
            'image_attributes'           : self.image_attributes,
            'link_attributes'            : self.link_attributes,
            'table_attributes'           : self.table_attributes,
            'table_body_attributes'      : self.table_body_attributes,
            'table_cell_attributes'      : self.table_cell_attributes,
            'table_common_attributes'    : self.table_common_attributes,
            'table_footer_attributes'    : self.table_footer_attributes,
            'table_header_attributes'    : self.table_header_attributes,
            'table_row_attributes'       : self.table_row_attributes,
            'site_charset'               : self.site_charset,
            'site_content_type'          : self.site_content_type,
            'site_language'              : self.site_language,
            'site_language_dir'          : self.site_language_dir,
            'site_languages'             : self.site_languages,
            'site_name'                  : self.site_name,
            'site_theme_name'            : self.site_theme_name,
            'render_block'               : self.render_block,
            'render_body'                : self.render_body,
            'render_dict'                : self.render_dict,
            'render_dict_key'            : self.render_dict_key,
            'render_dict_value'          : self.render_dict_value,
            'render_html'                : self.render_html,
            'render_image'               : self.render_image,
            'render_link'                : self.render_link,
            'render_link_queries'        : self.render_link_queries,
            'render_links'               : self.render_links,
            'render_list'                : self.render_list,
            'render_list_item'           : self.render_list_item,
            'render_page'                : self.render_page,
            'render_region'              : self.render_region,
            'render_table'               : self.render_table,
            'render_table_bodies'        : self.render_table_bodies,
            'render_table_body'          : self.render_table_body,
            'render_table_cell'          : self.render_table_cell,
            'render_table_footer'        : self.render_table_footer,
            'render_table_header'        : self.render_table_header,
            'render_table_row'           : self.render_table_row,
            'render_table_rows'          : self.render_table_rows,
            'render_tag'                 : self.render_tag,
            'render_template'            : self.render_template,
            'render_template_source'     : self.render_template_source,
        })
        return d

    def get_user(self,request=None):
        if request and hasattr(request,'user'):
            user = request.user or AnonymousUser()
        else:
            user = AnonymousUser()
        return user

    def get_template(self,name):
        if self.theme.is_current:
            name = os.path.join(CURRENT_THEME_PREFIX,name)
        else:
            name = os.path.join(self.theme.template_prefix,name)
        try:
            return self._templates[name]
        except KeyError:
            template              = loader.get_template(name)
            self._templates[name] = template
            return template

    def safe_url_path(self,url_path):
        url_path = posixpath.normpath(urllib.unquote(url_path))
        url_path = url_path.lstrip('/')
        new_path = ''
        for part in url_path.split('/'):
            if not part:
                continue
            drive,part = os.path.splitdrive(part)
            head,part  = os.path.split(part)
            if part in (os.curdir,os.pardir):
                continue
            new_path = os.path.join(new_path,part).replace('\\','/')
        return new_path

    def get_medium_url(self,name):
        name = self.safe_url_path(name)
        if os.path.isfile(os.path.join(settings.MEDIA_ROOT,name)):
            return settings.MEDIA_URL + name
        elif Theme.objects.get_current().has_medium(name):
            return Theme.objects.get_current().get_medium().url
        raise MediumDoesNotExist,"Medium '{0}' does not exist".format(name)

class ExtensionRenderer(BaseRenderer):
    def __getattr__(self,name):
        try:
            return self._theme.get_render_function(name)
        except Exception:
            raise AttributeError,"{0} object has no attribute {1}".format(type(self).__name__,name)
    
class ApplicationRenderer(ExtensionRenderer):
    def __init__(self,theme):
        super(ApplicationRenderer,self).__init__(theme)

class ContainerRenderer(ExtensionRenderer):
    def __init__(self,theme,container):
        from sitepal.sitetheme.models import LayoutContainer
        assert isinstance(container,LayoutContainer)
        self._container = container
        super(ContainerRenderer,self).__init__(theme)

    @property
    def container(self):
        return self._container
        
    @property
    def title(self):
        return self.container.title if self.container.display_title else None

    @property
    def title_type(self):
        return None

    @property
    def attributes(self):
        return self.container.attributes

    def is_visible(self,request):
        return self.container.is_visible(request)

    def render(self,request):
        raise NotImplementedError

    def render_content(self,request):
        return u''

class BlockRenderer(ContainerRenderer):
    def __init__(self,theme,block):
        from sitepal.sitetheme.models import LayoutBlock
        assert isinstance(block,LayoutBlock)
        super(BlockRenderer,self).__init__(theme,block)

    @property
    def block(self):
        return self._container

    def render(self,request):
        return self.render_block(title     =self.title,
                                 title_type=self.title_type,
                                 content   =self.render_content(request),
                                 attributes=self.attributes)

class TemplateBlockRenderer(BlockRenderer):
    def render_content(self,request):
        return self.render_template_source(source =self.block.source,request=request)

class RegionRenderer(ContainerRenderer):
    def __init__(self,theme,region):
        from sitepal.sitetheme.models import LayoutRegion
        assert isinstance(region,LayoutRegion)
        super(RegionRenderer,self).__init__(theme,region)

    @property
    def region(self):
        return self._container

    def render_content(self,request):
        output = []
        for block in self.region.blocks:
            output.append(block.render(self.theme,request))
        return self.safe(u''.join(output))

    def render(self,request):
        return self.render_region(content=self.render_content(request),attributes=self.attributes)

